#include <srs_core_mem_watch.hpp>

#ifdef SRS_AUTO_MEM_WATCH

#include <map>
#include <stdio.h>
using namespace std;

struct SrsMemoryObject {
    void* ptr;
    std::string category;
    int size;
};

std::map<void*, SrsMemoryObject*> _srs_ptrs;

void srs_memory_watch(void* ptr, string category, int size) {
    SrsMemoryObject* obj = NULL;

    auto it = _srs_ptrs.find(ptr);
    if (it != _srs_ptrs.end()) {
        obj = it->second;
    } else {
        obj = new SrsMemoryObject();
        _srs_ptrs[ptr] = obj;
    }

    obj->ptr = ptr;
    obj->category = category;
    obj->size = size;
}

void srs_memory_unwatch(void* ptr) {
    auto it = _srs_ptrs.find(ptr);
    if (it != _srs_ptrs.end()) {
        SrsMemoryObject* obj = it->second;
        srs_freep(obj);
        _srs_ptrs.erase(it);
    }
}

void srs_memory_report() {
    printf("srs memory watch leak report:\n");

    int total = 0;
    for (auto it = _srs_ptrs.begin(); it != _srs_ptrs.end(); ++it) {
        auto obj = it->second;
        if(obj == nullptr) {
            continue;
        }
        printf("    %s: %#" PRIx64 ", %dB\n", obj->category.c_str(), (int64_t)obj->ptr, obj->size);
        total += obj->size;
    }

    printf("%d objects leak %dKB.\n", (int)_srs_ptrs.size(), total / 1024);
    printf("@remark use script to cleanup for memory watch: ./etc/init.d/srs stop\n");
}

#endif

